NexusPi Git Node
MdnsService.h v1.0.45 (4db65df3) Text, 4.41 KB
T8b949e// MdnsService.h — mDNS / zeroconf service for RTNode
T8b949e//
T8b949e// Publishes the node's STA hostname and a `_reticulum._tcp` service so peers
T8b949e// on the same LAN can discover the local TCP server without a static IP or
T8b949e// router DHCP reservation. In config-portal AP mode publishes a fixed name
T8b949e// (`rtnode.local`) so the captive portal can be reached by name.
T8b949e//
T8b949e// Header-only; safe to include from multiple translation units thanks to the
T8b949e// `inline` linkage and a single static state variable per build.
Tff7b72#Tff7b72pragma once
Tff7b72#Tff7b72include T8b949e<ESPmDNS.h>
Tff7b72#Tff7b72include T8b949e<WiFi.h>
Te6edf3namespace Te6edf3mdns_service Tb4b4b4{
Tff7b72inline Tffa657boolTff7b72& Td2a8ffrunning_refTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72static Tffa657bool Te6edf3running Tff7b72= Tffa657falseTb4b4b4;
Tff7b72return Te6edf3runningTb4b4b4;
Tb4b4b4}
T8b949e// Normalize a hostname for mDNS: lowercase ASCII, replace anything outside
T8b949e// [a-z0-9-] with '-'. Writes at most `out_size-1` chars + NUL into `out`.
Tff7b72inline Tffa657void Td2a8ffnormalize_hostnameTb4b4b4(Tff7b72const Tffa657charTff7b72* Te6edf3inTb4b4b4, Tffa657charTff7b72* Te6edf3outTb4b4b4, Tffa657size_t Te6edf3out_sizeTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3out_size Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tff7b72returnTb4b4b4;
Tffa657size_t Te6edf3j Tff7b72= T79c0ff0Tb4b4b4;
Tff7b72for Tb4b4b4(Tffa657size_t Te6edf3i Tff7b72= T79c0ff0Tb4b4b4; Te6edf3inTb4b4b4[Te6edf3iTb4b4b4] Tff7b72!Tff7b72= T79c0ff0 Tff7b72&Tff7b72& Te6edf3j Tff7b72+ T79c0ff1 Tff7b72< Te6edf3out_sizeTb4b4b4; Tff7b72+Tff7b72+Te6edf3iTb4b4b4) Tb4b4b4{
Tffa657char Te6edf3c Tff7b72= Te6edf3inTb4b4b4[Te6edf3iTb4b4b4]Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3c Tff7b72>Tff7b72= Ta5d6ff'Ta5d6ffATa5d6ff' Tff7b72&Tff7b72& Te6edf3c Tff7b72<Tff7b72= Ta5d6ff'Ta5d6ffZTa5d6ff'Tb4b4b4) Te6edf3c Tff7b72= Te6edf3c Tff7b72- Ta5d6ff'Ta5d6ffATa5d6ff' Tff7b72+ Ta5d6ff'Ta5d6ffaTa5d6ff'Tb4b4b4;
Tffa657bool Te6edf3ok Tff7b72= Tb4b4b4(Te6edf3c Tff7b72>Tff7b72= Ta5d6ff'Ta5d6ffaTa5d6ff' Tff7b72&Tff7b72& Te6edf3c Tff7b72<Tff7b72= Ta5d6ff'Ta5d6ffzTa5d6ff'Tb4b4b4) Tff7b72|Tff7b72| Tb4b4b4(Te6edf3c Tff7b72>Tff7b72= Ta5d6ff'Ta5d6ff0Ta5d6ff' Tff7b72&Tff7b72& Te6edf3c Tff7b72<Tff7b72= Ta5d6ff'Ta5d6ff9Ta5d6ff'Tb4b4b4) Tff7b72|Tff7b72| Te6edf3c Tff7b72=Tff7b72= Ta5d6ff'Ta5d6ff-Ta5d6ff'Tb4b4b4;
Te6edf3outTb4b4b4[Te6edf3jTff7b72+Tff7b72+Tb4b4b4] Tff7b72= Te6edf3ok Tff7b72? Te6edf3c Tff7b72: Ta5d6ff'Ta5d6ff-Ta5d6ff'Tb4b4b4;
Tb4b4b4}
Te6edf3outTb4b4b4[Te6edf3jTb4b4b4] Tff7b72= T79c0ff0Tb4b4b4;
Tb4b4b4}
T8b949e// Resolve the effective mDNS hostname: honor `custom` if non-empty, otherwise
T8b949e// fall back to `rtnode<XXXX>` where XXXX = `default_suffix` (typically the
T8b949e// last 4 hex chars of the device MAC). Output is normalized.
Tff7b72inline Tffa657void Td2a8ffresolve_hostnameTb4b4b4(Tff7b72const Tffa657charTff7b72* Te6edf3customTb4b4b4, Tff7b72const Tffa657charTff7b72* Te6edf3default_suffixTb4b4b4,
Tffa657charTff7b72* Te6edf3outTb4b4b4, Tffa657size_t Te6edf3out_sizeTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3custom Tff7b72!Tff7b72= Tffa657nullptr Tff7b72&Tff7b72& Te6edf3customTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72!Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3normalize_hostnameTb4b4b4(Te6edf3customTb4b4b4, Te6edf3outTb4b4b4, Te6edf3out_sizeTb4b4b4)Tb4b4b4;
Tb4b4b4} Tff7b72else Tb4b4b4{
Tffa657char Te6edf3fallbackTb4b4b4[T79c0ff16Tb4b4b4]Tb4b4b4;
Te6edf3snprintfTb4b4b4(Te6edf3fallbackTb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3fallbackTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ffrtnode%sTa5d6ff"Tb4b4b4,
Te6edf3default_suffix Tff7b72!Tff7b72= Tffa657nullptr Tff7b72? Te6edf3default_suffix Tff7b72: Ta5d6ff"Ta5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3normalize_hostnameTb4b4b4(Te6edf3fallbackTb4b4b4, Te6edf3outTb4b4b4, Te6edf3out_sizeTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
T8b949e// Start mDNS in STA mode and (optionally) advertise the local TCP server.
T8b949e// `hostname` is the .local name — case and stray chars are normalized.
T8b949e// `tcp_port == 0` means "do not advertise the _reticulum._tcp service".
Tff7b72inline Tffa657bool Td2a8ffstart_staTb4b4b4(Tff7b72const Tffa657charTff7b72* Te6edf3hostnameTb4b4b4, Tffa657uint16_t Te6edf3tcp_portTb4b4b4) Tb4b4b4{
Tffa657boolTff7b72& Te6edf3running Tff7b72= Te6edf3running_refTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3runningTb4b4b4) Tff7b72return Tffa657trueTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3hostname Tff7b72=Tff7b72= Tffa657nullptr Tff7b72|Tff7b72| Te6edf3hostnameTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tff7b72return Tffa657falseTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3WiFiTb4b4b4.Te6edf3statusTb4b4b4(Tb4b4b4) Tff7b72!Tff7b72= Te6edf3WL_CONNECTEDTb4b4b4) Tff7b72return Tffa657falseTb4b4b4;
Tffa657char Te6edf3normTb4b4b4[T79c0ff32Tb4b4b4]Tb4b4b4;
Te6edf3normalize_hostnameTb4b4b4(Te6edf3hostnameTb4b4b4, Te6edf3normTb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3normTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3normTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tff7b72return Tffa657falseTb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3MDNSTb4b4b4.Te6edf3beginTb4b4b4(Te6edf3normTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3SerialTb4b4b4.Te6edf3printlnTb4b4b4(Ta5d6ff"Ta5d6ff[mDNS] begin() failed in STA modeTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72return Tffa657falseTb4b4b4;
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3tcp_port Tff7b72!Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3MDNSTb4b4b4.Te6edf3addServiceTb4b4b4(Ta5d6ff"Ta5d6ffreticulumTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fftcpTa5d6ff"Tb4b4b4, Te6edf3tcp_portTb4b4b4)Tb4b4b4;
Te6edf3MDNSTb4b4b4.Te6edf3addServiceTxtTb4b4b4(Ta5d6ff"Ta5d6ffreticulumTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fftcpTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffkindTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6ffrtnode-heltecTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3running Tff7b72= Tffa657trueTb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printTb4b4b4(Ta5d6ff"Ta5d6ff[mDNS] STA up: Ta5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printTb4b4b4(Te6edf3normTb4b4b4)Tb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printTb4b4b4(Ta5d6ff"Ta5d6ff.localTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3tcp_port Tff7b72!Tff7b72= T79c0ff0Tb4b4b4) Tb4b4b4{
Te6edf3SerialTb4b4b4.Te6edf3printTb4b4b4(Ta5d6ff"Ta5d6ff (_reticulum._tcp port Ta5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printTb4b4b4(Te6edf3tcp_portTb4b4b4)Tb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printTb4b4b4(Ta5d6ff"Ta5d6ff)Ta5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Te6edf3SerialTb4b4b4.Te6edf3printlnTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72return Tffa657trueTb4b4b4;
Tb4b4b4}
T8b949e// Start mDNS in AP mode for the config portal. The hostname is fixed so
T8b949e// users can always type the same .local address regardless of which device
T8b949e// they are configuring.
Tff7b72inline Tffa657bool Td2a8ffstart_ap_configTb4b4b4(Tff7b72const Tffa657charTff7b72* Te6edf3hostnameTb4b4b4) Tb4b4b4{
Tffa657boolTff7b72& Te6edf3running Tff7b72= Te6edf3running_refTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3runningTb4b4b4) Tff7b72return Tffa657trueTb4b4b4;
Tff7b72if Tb4b4b4(Te6edf3hostname Tff7b72=Tff7b72= Tffa657nullptr Tff7b72|Tff7b72| Te6edf3hostnameTb4b4b4[T79c0ff0Tb4b4b4] Tff7b72=Tff7b72= T79c0ff0Tb4b4b4) Tff7b72return Tffa657falseTb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3MDNSTb4b4b4.Te6edf3beginTb4b4b4(Te6edf3hostnameTb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3SerialTb4b4b4.Te6edf3printlnTb4b4b4(Ta5d6ff"Ta5d6ff[mDNS] begin() failed in AP modeTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72return Tffa657falseTb4b4b4;
Tb4b4b4}
Te6edf3MDNSTb4b4b4.Te6edf3addServiceTb4b4b4(Ta5d6ff"Ta5d6ffhttpTa5d6ff"Tb4b4b4, Ta5d6ff"Ta5d6fftcpTa5d6ff"Tb4b4b4, T79c0ff80Tb4b4b4)Tb4b4b4;
Te6edf3running Tff7b72= Tffa657trueTb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printTb4b4b4(Ta5d6ff"Ta5d6ff[mDNS] AP up: Ta5d6ff"Tb4b4b4)Tb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printTb4b4b4(Te6edf3hostnameTb4b4b4)Tb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printlnTb4b4b4(Ta5d6ff"Ta5d6ff.localTa5d6ff"Tb4b4b4)Tb4b4b4;
Tff7b72return Tffa657trueTb4b4b4;
Tb4b4b4}
T8b949e// Convenience: derive the MAC-suffix fallback automatically and start the STA
T8b949e// service. Equivalent to manually calling resolve_hostname() + start_sta().
Tff7b72inline Tffa657bool Td2a8ffstart_sta_autoTb4b4b4(Tff7b72const Tffa657charTff7b72* Te6edf3customTb4b4b4, Tffa657uint16_t Te6edf3tcp_portTb4b4b4) Tb4b4b4{
Tffa657uint8_t Te6edf3macTb4b4b4[T79c0ff6Tb4b4b4]Tb4b4b4;
Te6edf3WiFiTb4b4b4.Te6edf3macAddressTb4b4b4(Te6edf3macTb4b4b4)Tb4b4b4;
Tffa657char Te6edf3suffixTb4b4b4[T79c0ff5Tb4b4b4]Tb4b4b4;
Te6edf3snprintfTb4b4b4(Te6edf3suffixTb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3suffixTb4b4b4)Tb4b4b4, Ta5d6ff"Ta5d6ff%02x%02xTa5d6ff"Tb4b4b4, Te6edf3macTb4b4b4[T79c0ff4Tb4b4b4]Tb4b4b4, Te6edf3macTb4b4b4[T79c0ff5Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tffa657char Te6edf3nameTb4b4b4[T79c0ff33Tb4b4b4]Tb4b4b4;
Te6edf3resolve_hostnameTb4b4b4(Te6edf3customTb4b4b4, Te6edf3suffixTb4b4b4, Te6edf3nameTb4b4b4, Tff7b72sizeofTb4b4b4(Te6edf3nameTb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3start_staTb4b4b4(Te6edf3nameTb4b4b4, Te6edf3tcp_portTb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72inline Tffa657void Td2a8ffstopTb4b4b4(Tb4b4b4) Tb4b4b4{
Tffa657boolTff7b72& Te6edf3running Tff7b72= Te6edf3running_refTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3runningTb4b4b4) Tff7b72returnTb4b4b4;
Te6edf3MDNSTb4b4b4.Te6edf3endTb4b4b4(Tb4b4b4)Tb4b4b4;
Te6edf3running Tff7b72= Tffa657falseTb4b4b4;
Te6edf3SerialTb4b4b4.Te6edf3printlnTb4b4b4(Ta5d6ff"Ta5d6ff[mDNS] stoppedTa5d6ff"Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tff7b72inline Tffa657bool Td2a8ffis_runningTb4b4b4(Tb4b4b4) Tb4b4b4{ Tff7b72return Te6edf3running_refTb4b4b4(Tb4b4b4)Tb4b4b4; Tb4b4b4}
Tb4b4b4} T8b949e// namespace mdns_service
Served by rngit 1.5.0 - Generated in 0.02s